package edu.aynu.core;

import com.fasterxml.jackson.annotation.JsonIgnore;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

/**
 * @Author: haha
 * @Date: 2021/5/10 21:44
 * @Description: 安全性算法
 */
public class Safety {


    private Bankers bankers;

    /**
     * 安全列表
     */
    private List<Integer> safe = new LinkedList<>();

    /**
     * 工作向量
     * 实际等于bankers.getAvailable()
     */
    private int[] work;

    /**
     * 记录数据的转换过程，为可视化提供数据
     */
    private List<Data> recordList = new LinkedList<>();

    public Safety() {

    }

    public Safety(Bankers bankers) {
        this.bankers = bankers;
        work = bankers.getAvailable();
        for (int i = 0; i < bankers.getName().length; i++) {
            safe.add(i);
        }
    }

    /**
     * 判断系统是否处于安全状态
     * @return 安全返回true,不安全返回false
     */
    @JsonIgnore
    public boolean isSafe() {

        while (safe.size() > 0) {

            int safeFlag = -1;
            for (int i : safe) {

                boolean repayFlag = true;
                for (int j = 0; j < work.length; j++) {
                    if (work[j] < bankers.getNeed()[i][j]) {
                        repayFlag = false;
                        break;
                    }
                }
                // 可以偿还
                if (repayFlag) {
                    Data data = new Data(bankers);
                    data.name = bankers.getName()[i];
                    data.need = bankers.getNeed()[i];
                    data.allocation = bankers.getAllocation()[i];
                    for (int j = 0; j < work.length; j++) {
                        work[j] += bankers.getAllocation()[i][j];
                        data.workAndAllocation[j] = work[j];
                    }
                    recordList.add(data);
                    safeFlag = safe.indexOf(i);
                    break;
                }
            }
            if (safeFlag != -1) {
                safe.remove(safeFlag);
            } else {
                return false;
            }
        }
        return true;
    }

    public List<Data> getRecordList() {
        return recordList;
    }

    static class Data {
        /**
         * 贷款者
         */
        String name;

        /**
         * 工作向量
         */
        int[] work;

        /**
         * 需求向量
         */
        int[] need;

        /**
         * 分配向量
         */
        int[] allocation;

        /**
         * 偿还总额
         */
        int[] workAndAllocation;

        /**
         * 是否偿还
         */
        boolean finish;

        Data(Bankers bankers) {
            int num = bankers.getAvailable().length;
            this.work = new int[num];
            for (int i = 0; i < num; i++) {
                work[i] = bankers.getAvailable()[i];
            }
            this.workAndAllocation = new int[num];
            this.finish = true;

        }

        Data() {

        }

        public String getName() {
            return name;
        }

        public int[] getWork() {
            return work;
        }

        public int[] getNeed() {
            return need;
        }

        public int[] getAllocation() {
            return allocation;
        }

        public int[] getWorkAndAllocation() {
            return workAndAllocation;
        }

        public boolean isFinish() {
            return finish;
        }

        @Override
        public String toString() {
            return "Data{" +
                    "name='" + name + '\'' +
                    ", work=" + Arrays.toString(work) +
                    ", need=" + Arrays.toString(need) +
                    ", allocation=" + Arrays.toString(allocation) +
                    ", workAndAllocation=" + Arrays.toString(workAndAllocation) +
                    ", finish=" + finish +
                    "}\n";
        }
    }
}
